#include "head.h"
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <arpa/inet.h>
#include <pthread.h>
#include "MQTTClient.h"

#define ADDRESS     "tcp://192.168.1.210:1883"
#define CLIENTID    "ExampleClientSub"
#define TOPIC_FLAG "MQTT Flag"
#define TOPIC_COUNT "MQTT Count"
#define QOS         1    //服务质量
#define TIMEOUT     10000L  //超时时长 

volatile int people_flag;      // 有人1 没人0
volatile int people_count; // 人数

//定义一个用于表示发布消息的令牌，并使其具有易变性
volatile MQTTClient_deliveryToken deliveredtoken;
//定义一个消息投递回调函数，用于提示消息是否成功投递
void delivered(void *context, MQTTClient_deliveryToken dt)
{
    printf("已确认令牌值%d消息的传递\n", dt);
    deliveredtoken = dt;
}
//定义一个消息到达回调函数，用于处理接收到的消息
int msgarrvd(void *context, char *topicName, int topicLen, MQTTClient_message *message)
{
    int i;
    char* payloadptr;

    printf("收到消息\n");
    printf("   主题: %s\n", topicName);
    printf("   消息: ");

    payloadptr = message->payload;
    for(i=0; i<message->payloadlen; i++)
    {
        putchar(*payloadptr++);
    }
    putchar('\n');
    //接收人数到people_count
    sscanf(message->payload, "%d", &people_count);
    printf("pp_count=%d\n",people_count);
    MQTTClient_freeMessage(&message);
    MQTTClient_free(topicName);
    return 1;
}

// 处理mqttpub
void *mqtt_handle(void *arg)
{
    // 1 创建了MQTTClient对象
    MQTTClient client;                                                           
    MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;  //连接选项 
    MQTTClient_message pubmsg = MQTTClient_message_initializer;  //发布消息                
    MQTTClient_deliveryToken token;  //令牌                                            
    int rc;  
    char ch;                                                                    

    // 2 使用指定的地址和客户端 ID 创建 MQTT 客户端
    MQTTClient_create(&client, ADDRESS, CLIENTID, MQTTCLIENT_PERSISTENCE_NONE, NULL);
    // 3 初始化连接选项，并设置保活时间和清除会话标志
    conn_opts.keepAliveInterval = 20; // 2
    conn_opts.cleansession = 1;

    // 4设置 MQTT 客户端回调函数 丢失回调 消息到达回调 消息投递回调
    MQTTClient_setCallbacks(client, NULL, NULL, msgarrvd, delivered);

    // 6 使用连接选项连接到 MQTT 代理服务器
    if ((rc = MQTTClient_connect(client, &conn_opts)) != MQTTCLIENT_SUCCESS)
    {
        printf("连接MQTT服务器失败, return code %d\n", rc);
        exit(EXIT_FAILURE);
    }

    printf("订阅主题：%s\n 客户端ID：%s 服务质量%d\n\n"
           "Press Q<Enter> to quit\n\n", TOPIC_COUNT, CLIENTID, QOS);
    //6订阅指定的主题
    MQTTClient_subscribe(client, TOPIC_COUNT, QOS);
    
    char payload[128] = "";
    while (1)
    {
        // 1 设置发布消息的内容、长度、QoS 等级和保留标志
        sprintf(payload,"%d",people_flag);
        pubmsg.payload = payload;
        pubmsg.payloadlen = (int)strlen(payload);
        pubmsg.qos = QOS;
        pubmsg.retained = 0;
        // 2 发布消息到指定的主题，并获取传递令牌
        MQTTClient_publishMessage(client, TOPIC_FLAG, &pubmsg, &token);
        printf("等待 %d 秒 发送内容：%s\n"
               "主题：%s 客户端ID：%s\n",
               (int)(TIMEOUT / 1000), (char *)pubmsg.payload, TOPIC_FLAG, CLIENTID);
        // 3 等待指定时间，直到消息传递完成，并获取结果
        rc = MQTTClient_waitForCompletion(client, token, TIMEOUT);
        printf("传递了传递令牌（%d）的消息\n\n", token);
        
        usleep(2000000);  // 2 秒钟发送一次数据
    }
    //7订阅指定的主题
    MQTTClient_unsubscribe(client, TOPIC_COUNT);
    // 8 断开 MQTT 客户端的连接
    MQTTClient_disconnect(client, 10000);
    // 9 销毁 MQTTClient 对象
    MQTTClient_destroy(&client);
    return (void *)rc;
}

void *buzzer_motor_fan_handle(void *arg) // arg = &fd3
{
    while (1)
    {
        ioctl(*((int *)arg), SENT_PEOPLE_COUNT, &people_count); // 传递给蜂鸣器马达风扇
        // printf("%d\n",*((int *)arg));
    }
    pthread_exit(NULL);
}

void *rda226_handle(void *arg) // arg = &fd2
{
    while (1)
    {
        ioctl(*((int *)arg), SENT_PEOPLE_COUNT, &people_count); // 传递给数码管
        // printf("%d\n",*((int *)arg));
    }
    pthread_exit(NULL);
}

int main(int argc, const char *argv[])
{
    int fd1 = open("/dev/rda226", O_RDWR);
    if (fd1 < 0)
    {
        printf("设备文件fd1打开失败\n");
        exit(-1);
    }
    int fd2 = open("/dev/m74hc595", O_RDWR);
    if (fd2 < 0)
    {
        printf("设备文件fd2打开失败\n");
        exit(-1);
    }
    int fd3 = open("/dev/buzzer_motor_fan", O_RDWR);
    if (fd3 < 0)
    {
        printf("设备文件fd3打开失败\n");
        exit(-1);
    }

    // 采用多线程
    pthread_t tid1, tid2, tid3;
    if (pthread_create(&tid1, NULL, rda226_handle, (void *)&fd2) != 0)
    {
        fprintf(stderr, "pthread_create fail__%d__\n", __LINE__);
        return -1;
    }
    if (pthread_create(&tid2, NULL, buzzer_motor_fan_handle, (void *)&fd3) != 0)
    {
        fprintf(stderr, "pthread_create fail__%d__\n", __LINE__);
        return -1;
    }
    if (pthread_create(&tid3, NULL, mqtt_handle, NULL) != 0)
    {
        fprintf(stderr, "pthread_create fail__%d__\n", __LINE__);
        return -1;
    }

    printf("pepple_cout=%d\n", people_count);

    while (1)
    {
        // 读取有人标志
        read(fd1, (void *)&people_flag, sizeof(people_flag));
        printf("pepple_flag=%d(1有人 0没人)\n", people_flag);
        sleep(1);
    }
    pthread_join(tid1, NULL);
    pthread_join(tid2, NULL);
    pthread_join(tid3, NULL);

    return 0;
}